#include "stdafx.h"
#include "IOCPNetwork.h"
#include <MSWSock.h>


IOCPNetwork::IOCPNetwork()
	:hrt(true),
	thread(0),
	iopcHandle(NULL),
	isAlreadyInitialize(false),
	lastErrorCode(0)
{
}


IOCPNetwork::~IOCPNetwork()
{
}

int IOCPNetwork::init(unsigned int thread)
{
	if (thread == 0)
	{
		SYSTEM_INFO systemInfo;

		GetSystemInfo(&systemInfo);

		//线程数等于cpu核数
		thread = systemInfo.dwNumberOfProcessors;
	}
	else if (thread > 64)
	{
		thread = 5;
	}

	assert(NULL == this->iopcHandle);
	/**
	 * 创建完成端口CreateIoCompletionPort函数关联一个已打开的文件实例和新建的或已存在的I/0完成端口，
	 * 或者创建一个未关联任何文件的I/O完成端口。
	 * FileHandle是有效的文件句柄或INVALID_HANDLE_VALUE。
	 * ExistingCompletionPort是已经存在的完成端口。如果为NULL，则为新建一个IOCP。
	 * CompletionKey是传送给处理函数的参数。
	 * NumberOfConcurrentThreads是有多少个线程在访问这个消息队列。
		当参数ExistingCompletionPort不为0的时候，系统忽略该参数，
		当该参数为0表示允许同时相等数目于处理器个数的线程访问该消息队列。
	 */
	if (NULL == (this->iopcHandle = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, thread)))
	{
		this->lastErrorCode = GetLastError();

		this->destory();

		return IOCP_UNDEFINED;
	}

	//初始化定时器队列
	this->timeQueue.init();

	//初始化同步对象池
	lockPool.initialize(0);

	assert(NULL == this->threadIdArray);

	//创建工作线程
	if (this->threadIdArray)
	{
		delete[] this->threadIdArray;
	}

	this->thread = thread;

	this->threadIdArray = new uintptr_t[thread];

	assert(this->threadIdArray);
	//数组初始化为0
	memset(this->threadIdArray, 0, sizeof(unsigned int) *thread);

	/*
		用来创建一个线程
		unsigned long _beginthreadex(

		void *security,    // 安全属性， 为NULL时表示默认安全性

		unsigned stack_size,    // 线程的堆栈大小， 一般默认为0

		unsigned(_stdcall *start_address)(void *),    // 所要启动的线程函数

		void *argilist, // 线程函数的参数， 是一个void*类型， 传递多个参数时用结构体

		unsigned initflag,    // 新线程的初始状态，0表示立即执行，CREATE_SUSPEND表示创建之后挂起
		unsigned *threaddr    // 成功返回新线程句柄， 失败返回0

		);
	*/

	for (uintptr_t i = 0; i < thread; i++)
	{
		if (0 == (this->threadIdArray[i] = _beginthreadex(NULL, 0, serviceCallBack, this, 0, NULL)))
		{
			this->lastErrorCode = GetLastError();
			this->destory();
			return IOCP_UNDEFINED;
		}
	}

	this->isAlreadyInitialize = true;

	return IOCP_SUCESS;
}

int IOCPNetwork::destory()
{
	//TODO

	if (this->threadIdArray)
	{
		// 获取当前工作线程

		uintptr_t currentThread = reinterpret_cast<uintptr_t>(GetCurrentThread());

		for (size_t i = 0; i < this->thread; i++)
		{
			if (currentThread == this->threadIdArray[i])
			{
				// 销毁失败
				return IOCP_DESTROYFAILED;
			}
		}
	}

	// 设置停止标志
	this->isAlreadyInitialize = false;

	// 发送退出通知，确保工作线程都从GetQueuedCompletionStatus阻塞中返回并终止运行.


	if (this->threadIdArray)
	{
		assert(this->thread > 0);

		if (this->iopcHandle)
		{
			for (size_t i = 0; i < this->thread; i++)
			{
				//PostQueuedCompletionStatus函数，向每个工作者线程都发送—个特殊的完成数据包。该函数会指示每个线程都“立即结束并退出”.下面是

				/*
				  CompletionPort：指定想向其发送一个完成数据包的完成端口对象。
				  dwNumberOfBytesTrlansferred：指定—个值,直接传递给GetQueuedCompletionStatus函数中对应的参数
				  dwCompletlonKey：指定—个值,直接传递给GetQueuedCompletionStatus函数中对应的参数
				  lpoverlapped：指定—个值,直接传递给GetQueuedCompletionStatus函数中对应的参数
				*/
				PostQueuedCompletionStatus(this->iopcHandle, 0, NULL, NULL);
			}
		}

		HANDLE handle = NULL;

		for (size_t i = 0; i < this->thread; i++)
		{
			if (this->threadIdArray[i])
			{
				handle = reinterpret_cast<HANDLE>(this->threadIdArray[i]);

				WaitForSingleObject(handle, INFINITE);

				CloseHandle(handle);
			}
		}
	}

	this->threadIdArray = NULL;

	this->thread = 0;

	// 关闭定时器
	this->timeQueue.destory();

	// 回收客户端链接资源

	if (this->connectStock.size() > 0)
	{
		for (std::map<HANDLE, IOCPContext*>::iterator itera = this->connectStock.begin(); itera != this->connectStock.end(); itera++)
		{
			IOCPContext* context = itera->second;

			if (!(context->status & IOCP_HANDLE_CLOSED))
			{
				CloseHandle(context);

				context->status |= IOCP_HANDLE_CLOSED;
			}

			delete context;
		}

		this->connectStock.clear();
	}

	this->lockPool.destory();


	return IOCP_SUCESS;
}

/*服务回调方法*/
unsigned int __stdcall IOCPNetwork::serviceCallBack(void * param)
{
	IOCPNetwork * iocp = reinterpret_cast<IOCPNetwork *>(param);



	while (1)
	{
		DWORD lpNumberOfBytesTransferred = 0;

		IOCPContext *iocpContnextKey = NULL;

		IOCPOverlappingStructure * iocpOverlapping = NULL;
		/*
			CompletionPort：指定的IOCP，该值由CreateIoCompletionPort函数创建。
			lpnumberofbytes：一次完成后的I/O操作所传送数据的字节数。
			lpcompletionkey：当文件I/O操作完成后，用于存放与之关联的CK。
			lpoverlapped：为调用IOCP机制所引用的OVERLAPPED结构。
			dwmilliseconds：用于指定调用者等待CP的时间。
			调用成功，则返回非零数值，相关数据存于lpNumberOfBytes、lpCompletionKey、lpoverlapped变量中。失败则返回零值。
		*/
		if (0 == GetQueuedCompletionStatus(iocp->iopcHandle, &lpNumberOfBytesTransferred, reinterpret_cast<PULONG_PTR>(&iocpContnextKey), reinterpret_cast<LPOVERLAPPED*>(&iocpOverlapping), INFINITE))
		{
			if (iocpOverlapping)
			{
				// 成功的成完成端口那拿到数据，但是 I/O 标记失败
				// 原因 1 远程主机关闭了远程连接
				// 原因 2 操作超时 
				iocp->onFinishedByIO(iocpContnextKey, iocpOverlapping, false, lpNumberOfBytesTransferred);
			}
			else
			{
				//句柄被关闭 在本程序属于正常退出
				return IOCP_UNDEFINED;
			}
		}
		else
		{
			//正常退出
			if (iocpContnextKey == NULL && iocpOverlapping == NULL && lpNumberOfBytesTransferred == 0)
			{
				TRACE("IOCPNetwork::serviceProc()IOCP工作线程退出.\r\n");
				break;
			}

			iocp->onFinishedByIO(iocpContnextKey, iocpOverlapping, true, lpNumberOfBytesTransferred);
		}
	}
	return 0;
}

void __stdcall IOCPNetwork::delayTimeBySend(void * param, unsigned char str)
{

}

void __stdcall IOCPNetwork::readTimeoutProc(void * param, unsigned char str)
{
	
}

void IOCPNetwork::onFinishedByIO(IOCPContext *iocpContnext, IOCPOverlappingStructure *olp, bool result, int transfer)
{

	if (olp->timer != NULL)
	{
		// 清除定时器
		// this->timeQueue

		this->timeQueue.deleteTimer(olp->timer, true);

		olp->timer = NULL;

	}

	IOCPProcCallBack func = olp->proc;

	if (iocpContnext->rwLock)
	{
		iocpContnext->rwLock->readLock();
	}

	if (result)
	{
		olp->sendDataNUmber += transfer;
	}

	olp->lastCompleteTime = this->hrt.getNow();


	int status = olp->status;

	byte *buffer = olp->buffer;

	size_t length = olp->length;

	void * param = olp->param;

	this->cleanOlp(olp);


	if (iocpContnext->status != IOCP_NORMAL)
	{
		status |= iocpContnext->status;
	}

	if (iocpContnext->rwLock)
	{
		iocpContnext->rwLock->unLock();
	}

	if (func)
	{
		func(iocpContnext, status, result, olp->sendDataNUmber, buffer, length, param);
	}
}

void IOCPNetwork::cleanOlp(IOCPOverlappingStructure * olp)
{
	olp->buffer = NULL;

	memset(&olp->ovp, 0, sizeof(OVERLAPPED));

	olp->param = NULL;

	olp->proc = NULL;

	olp->realLength = 0;

	olp->length = 0;

	olp->status = IOCP_NONE;

	if (olp->timer != NULL)
	{
		//删除定时器
		this->timeQueue.deleteTimer(olp->timer, false);

		olp->timer = NULL;
	}
}

int IOCPNetwork::realReceive(IOCPContext * iocp)
{
	DWORD lpNumberOfBytesRecvd = 0;

	//接收事件信息
	if (iocp->type = IOCP_HANDLE_SOCKET)
	{
		//socket 事件
		SOCKET socket = reinterpret_cast<SOCKET>(iocp->handler);

		WSABUF buff = { iocp->readBuff.length, reinterpret_cast<char*>(iocp->readBuff.buffer) };

		DWORD flags = 0;
		/*
			WSARecv()是从一个套接口接收数据的程序。主要用于在重叠模型中接收数据。
			s：一个标识已连接套接口的描述字。
			lpBuffers：一个指向WSABUF结构数组的指针。每一个WSABUF结构包含一个缓冲区的指针和缓冲区的长度。
			dwBufferCount：lpBuffers数组中WSABUF结构的数目。
			lpNumberOfBytesRecvd：如果接收操作立即结束，一个指向本调用所接收的字节数的指针。
			lpFlags：一个指向标志位的指针。 // 和函数socket()一样，和用来控制套接字的行为，例如，指出当前当前套接字是面向流的还是面向消息的。通常设置为0。
			lpOverlapped：一个指向WSAOVERLAPPED结构的指针（对于非重叠套接口则忽略）。
			lpCompletionRoutine：一个指向接收操作结束后调用的例程的指针（对于非重叠套接口则忽略）
		*/
		if (SOCKET_ERROR == WSARecv(socket, &buff, 1, &lpNumberOfBytesRecvd, &flags, reinterpret_cast<LPWSAOVERLAPPED>(&iocp->readBuff), NULL))
		{
			int code = WSAGetLastError();

			if (code != WSA_IO_PENDING)
			{
				this->lastErrorCode = code;

				return IOCP_UNDEFINED;
			}
		}
		return IOCP_PENDING;
	}
	else
	{
		//文件事件
		/*
		  从文件指针指向的位置开始将数据读出到一个文件中， 且支持同步和异步操作，
		  如果文件打开方式没有指明FILE_FLAG_OVERLAPPED的话，当程序调用成功时，它将实际读出文件的字节数保存到lpNumberOfBytesRead指明的地址空间中。
		  HANDLE hFile, 需要读入数据的文件指针,这个指针指向的文件必须是GENERIC_READ 访问属性的文件。
		  LPVOID lpBuffer，接收数据的缓冲区。
		  DWORD nNumberOfBytesToRead，指定要读取的字节数。
		  LPDWORD lpNumberOfBytesRead，指向一个DWORD类型变量的指针，用来接收读取的字节数。如果下一个参数为NULL，那么一定要传入这个参数。
		  LPOVERLAPPED lpOverlapped OVERLAPPED结构体指针,如果文件是以FILE_FLAG_OVERLAPPED方式打开的话,那么这个指针就不能为NULL。
		  FILE_FLAG_OVERLAPPED 允许对文件进行重叠操作
		  调用成功,返回非0
		  调用不成功,返回为0
		*/
		if (0 == ReadFile(iocp->handler, iocp->readBuff.buffer, iocp->readBuff.length, &lpNumberOfBytesRecvd, reinterpret_cast<LPOVERLAPPED>(&iocp->readBuff)))
		{
			int code = GetLastError();

			if (code != ERROR_IO_PENDING)
			{
				this->lastErrorCode = code;

				return IOCP_UNDEFINED;
			}
			return IOCP_PENDING;
		}
	}
}

size_t IOCPNetwork::realSend(IOCPContext * iocpContext)
{
	DWORD lpNumberOfBytesRecvd = 0;

	//接收事件信息
	if (iocpContext->type = IOCP_HANDLE_SOCKET)
	{
		//socket 事件
		SOCKET socket = reinterpret_cast<SOCKET>(iocpContext->handler);

		WSABUF buff = { iocpContext->writeBuff.length, reinterpret_cast<char*>(iocpContext->writeBuff.buffer) };
		/*
			WSASend()是从一个套接口接收数据的程序。主要用于在重叠模型中接收数据。
			s：一个标识已连接套接口的描述字。
			lpBuffers：一个指向WSABUF结构数组的指针。每一个WSABUF结构包含一个缓冲区的指针和缓冲区的长度。
			dwBufferCount：lpBuffers数组中WSABUF结构的数目。
			lpNumberOfBytesRecvd：如果接收操作立即结束，一个指向本调用所接收的字节数的指针。
			lpFlags：一个指向标志位的指针。 // 和函数socket()一样，和用来控制套接字的行为，例如，指出当前当前套接字是面向流的还是面向消息的。通常设置为0。
			lpOverlapped：一个指向WSAOVERLAPPED结构的指针（对于非重叠套接口则忽略）。
			lpCompletionRoutine：一个指向接收操作结束后调用的例程的指针（对于非重叠套接口则忽略）
		*/
		if (SOCKET_ERROR == WSASend(socket, &buff, 1, &lpNumberOfBytesRecvd, 0, reinterpret_cast<LPWSAOVERLAPPED>(&iocpContext->writeBuff), NULL))
		{
			int code = WSAGetLastError();

			if (code != WSA_IO_PENDING)
			{
				this->lastErrorCode = code;

				return IOCP_UNDEFINED;
			}
		}
		return IOCP_PENDING;
	}
	else
	{
		//文件事件
		/*
		  从文件指针指向的位置开始将数据读出到一个文件中， 且支持同步和异步操作，
		  如果文件打开方式没有指明FILE_FLAG_OVERLAPPED的话，当程序调用成功时，它将实际读出文件的字节数保存到lpNumberOfBytesRead指明的地址空间中。
		  HANDLE hFile, 需要写入数据的文件指针,这个指针指向的文件必须是GENERIC_READ 访问属性的文件。
		  LPVOID lpBuffer，写入数据的缓冲区。
		  DWORD nNumberOfBytesToRead，指定要写入的字节数。
		  LPDWORD lpNumberOfBytesRead，指向一个DWORD类型变量的指针，用来写入读取的字节数。如果下一个参数为NULL，那么一定要传入这个参数。
		  LPOVERLAPPED lpOverlapped OVERLAPPED结构体指针,如果文件是以FILE_FLAG_OVERLAPPED方式打开的话,那么这个指针就不能为NULL。
		  FILE_FLAG_OVERLAPPED 允许对文件进行重叠操作
		  调用成功,返回非0
		  调用不成功,返回为0
		*/
		if (0 == WriteFile(iocpContext->handler, iocpContext->writeBuff.buffer, iocpContext->writeBuff.length, &lpNumberOfBytesRecvd, reinterpret_cast<LPOVERLAPPED>(&iocpContext->writeBuff)))
		{
			int code = GetLastError();

			if (code != ERROR_IO_PENDING)
			{
				this->lastErrorCode = code;

				return IOCP_UNDEFINED;
			}
			return IOCP_PENDING;
		}
	}
}



//sockt库初始化窗口param  nMainVer主动发送 nSubVer被动发送
bool IOCPNetwork::initializeWindowSocket(WORD nMainVer, WORD nSubVer)
{
	WORD wr;

	WSAData ws;

	//https://baike.baidu.com/item/MAKEWORD/10741750(MAKEWORD 宏 平台：SDK这个宏创建一个无符号16位整型，通过连接两个给定的无符号参数。(注：typedef unsigned short WORD;))
	wr = MAKEWORD(nMainVer, nSubVer);

	/*	WSAStartup，即WSA(Windows Sockets Asynchronous，Windows异步套接字)的启动命令。
		是Windows下的网络编程接口软件Winsock1 或 Winsock2 里面的一个命令（Ps：Winsock 是由Unix下的BSD Socket发展而来,是一个与网络协议无关的编程接口）。
		WSAStartup必须是应用程序或DLL调用的第一个Windows Sockets函数。
		它允许应用程序或DLL指明Windows Sockets API的版本号及获得特定Windows Sockets实现的细节。
		应用程序或DLL只能在一次成功的WSAStartup()调用之后才能调用进一步的Windows Sockets API函数。
		(Winsock服务的初始化)
	*/
	return WSAStartup(wr, &ws) == 0;
}

int IOCPNetwork::accept(iocpKey key, SOCKET sockNew, byte * buf, size_t len, size_t timeout, IOCPProcCallBack func, void * param)
{
	// NO.1 检查是否已经初始化



	if (!this->isAlreadyInitialize)
	{
		return IOCP_UNINITIALIZED;
	}

	// NO.2 检查缓冲区
	int sockAddInLength = sizeof(sockaddr_in) + 16;
	int buffLength = sockAddInLength * 2;

	if (len < buffLength)
	{
		return 0;
	}

	// NO.3 完成键转化为上下文
	IOCPContext * iocpContnext = reinterpret_cast<IOCPContext*>(key);

	assert(iocpContnext->type == IOCP_HANDLE_SOCKET);

	// NO.4 
	SOCKET socket = reinterpret_cast<SOCKET>(iocpContnext->handler);

	GUID guid = WSAID_ACCEPTEX;

	LPFN_ACCEPTEX lpVoid = NULL;

	DWORD dWord = 0;

	/*
		控制一个套接口
		NO.2 将进行的操作的控制代码，即你所需要操控的类型，有如下几种：(获取扩展函数指针）
		NO.3 输入缓冲区的地址（如果你想指定一个函数对套接字进行控制，这里可以是一个guid，指定这个控制函数的guid）。
		NO.4 输入缓冲区的大小（这里为guid的大小，即sizeof(&guid)）
		NO.5 输出缓冲区的地址（这里即是函数指针的地址）
		NO.6 输出缓冲区的大小（函数指针的大小）。
		NO.7 输出实际字节数的地址。
		NO.8 WSAOVERLAPPED结构的地址（一般为NULL）
		No.9 一个指向操作结束后调用的例程指针（一般为NULL）。
		调用成功后，WSAIoctl ()函数返回0。
		否则的话，将返回SOCKET_ERROR错误，应用程序可通过WSAGetLastError()来获取相应的错误代码。
	*/
	if (0 != WSAIoctl(socket, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid), &lpVoid, sizeof(lpVoid), &dWord, NULL, NULL))
	{
		return WSAGetLastError();
	}

	// ping

	int status = IOCP_PENDING;

	if (iocpContnext->rwLock)
	{
		//同步加锁
		iocpContnext->rwLock->readLock();
	}

	if (iocpContnext->status != IOCP_NORMAL)
	{
		status = iocpContnext->status;
	}
	else if (this->sessionTimeout(iocpContnext))
	{
		status = IOCP_SESSIONTIMEO;
	}
	else
	{
		/* assert检查:不要同时投递多个同类型的操作,由程序逻辑确保这一点,而不用同步量以提高并发量,否则只能用互斥锁了. */

		assert(iocpContnext->readBuff.status == IOCP_NONE);

		iocpContnext->readBuff.status = IOCP_ACCEPT;

		iocpContnext->readBuff.buffer = buf;

		iocpContnext->readBuff.length = len;

		iocpContnext->readBuff.param = param;

		iocpContnext->readBuff.proc = func;

		iocpContnext->readBuff.timeout = timeout;

		iocpContnext->readBuff.realLength = len;

		if (timeout > 0)
		{
			//创建定时器

			iocpContnext->readBuff.timer = this->timeQueue.createTimer(timeout, readTimeoutProc, iocpContnext);
		}

		DWORD receiveDataLength = 0;

		if (!lpVoid(socket, sockNew, buf, buffLength, len - buffLength, sockAddInLength, &receiveDataLength, reinterpret_cast<LPOVERLAPPED>(&iocpContnext->readBuff)))
		{
			int res = WSAGetLastError();

			if (res != WSA_IO_PENDING)
			{
				status = IOCP_UNDEFINED;
			}
		}
		else
		{
			assert(0);
			return IOCP_UNDEFINED;
		}

	}

	if (iocpContnext->rwLock)
	{
		//同步解锁
		iocpContnext->rwLock->unLock();
	}

	return status;
}

iocpKey IOCPNetwork::add(SOCKET s, unsigned long sessionTimeo, unsigned long readSpeedLmt, unsigned long writeSpeedLmt, bool sync)
{
	//reinterpret_cast是C++里的强制类型转换符
	return add(reinterpret_cast<HANDLE>(s), sessionTimeo, readSpeedLmt, writeSpeedLmt, false, sync);
}

iocpKey IOCPNetwork::add(HANDLE f, unsigned long sessionTimeo, unsigned long readSpeedLmt, unsigned long writeSpeedLmt, bool sync)
{
	return add(f, sessionTimeo, readSpeedLmt, writeSpeedLmt, true, sync);
}

/*
 获取socket
*/
SOCKET IOCPNetwork::getSockopt(iocpKey param)
{

	IOCPContext *iocpContnext = reinterpret_cast<IOCPContext*>(param);

	assert(iocpContnext->type == IOCP_HANDLE_SOCKET);

	return reinterpret_cast<SOCKET> (iocpContnext->handler);
}

void IOCPNetwork::refresh(void * clientSocket)
{

}

int IOCPNetwork::remove(void* clientSocket)
{
	if (!this->isAlreadyInitialize)
	{
		return IOCP_UNDEFINED;
	}

	IOCPContext *context = reinterpret_cast<IOCPContext *>(clientSocket);

	if (context->rwLock)
	{
		context->rwLock->writeLock();
	}

	bool busy = false;

	if (context->readBuff.status != IOCP_NONE || context->writeBuff.status != IOCP_NONE)
	{
		busy = true;
	}
	else
	{
		/* 空闲状态,设置一个删除标志,禁止继续操作 */
		context->status |= IOCP_REMOVE;
	}

	if (context->rwLock)
	{
		context->rwLock->unLock();
	}

	if (busy)
	{
		return IOCP_BUSY;
	}

	//延时删除定时器
	if (context->readBuff.timer)
	{
		this->timeQueue.deleteTimer(context->readBuff.timer, true);
	}


	//延时删除定时器
	if (context->writeBuff.timer)
	{
		this->timeQueue.deleteTimer(context->writeBuff.timer, true);
	}

	// 加锁
	this->lockObj.lockUp();

	// 删除 链接客户端
	this->connectStock.erase(context->handler);

	// 释放锁
	this->lockObj.unLock();

	delete context;

	return IOCP_SUCESS;
}

int IOCPNetwork::receive(void * clientSocket, byte * clientSocketBuff, unsigned long clientBuffLen, unsigned long timeout, IOCPProcCallBack callBack, void * param)
{
	if (!this->isAlreadyInitialize)
	{
		//未初始化
		return IOCP_UNDEFINED;
	}

	IOCPContext *iocpContext = reinterpret_cast<IOCPContext*>(clientSocket);

	// 操作进行中
	int result = IOCP_PENDING;

	if (iocpContext->rwLock)
	{
		iocpContext->rwLock->readLock();
	}

	if (IOCP_NORMAL != iocpContext->status)
	{
		// 套接字正常 允许同时有一个读操作和写操作
		result = iocpContext->status;
	}
	else if (this->sessionTimeout(iocpContext))
	{
		result = IOCP_SESSIONTIMEO;
	}
	else
	{
		assert(iocpContext->readBuff.status == IOCP_NONE);

		iocpContext->readBuff.buffer = clientSocketBuff;

		iocpContext->readBuff.length = clientBuffLen;

		assert(iocpContext->readBuff.timer == NULL);

		iocpContext->readBuff.proc = callBack;

		iocpContext->readBuff.param = param;

		iocpContext->readBuff.timeout = timeout;

		iocpContext->readBuff.realLength = clientBuffLen;

		iocpContext->readBuff.status = IOCP_RECV;

		//检查是否超过速度限制
		size_t delay = 0;

		if (iocpContext->readBuff.speedLimit > 0 && iocpContext->readBuff.lastCompleteTime != 0)
		{
			//获取运行时间
			__int64 execTime = this->hrt.getCounter((iocpContext->readBuff.sendDataNUmber / iocpContext->readBuff.speedLimit) * 1.0);

			//完成时间
			execTime += iocpContext->startTime;

			//完成时间提前 说明时间超标
			if (iocpContext->readBuff.lastCompleteTime > execTime)
			{
				// 减少发送的包数据大小
				// 计算 定时器触发时间
				this->hrt.getMS(iocpContext->readBuff.lastCompleteTime - execTime);
			}
		}

		//超时
		if (delay > 0)
		{
			// 创建定时器，并返回成功.等真正定时器回调【回调函数】
			iocpContext->readBuff.status = IOCP_DELAY_READ;

			iocpContext->readBuff.timer = this->timeQueue.createTimer(delay, delayTimeByReceive, iocpContext);
		}
		else
		{
			//如果设置了超时时间
			if (iocpContext->readBuff.timeout > 0)
			{
				//创建定时器
				iocpContext->readBuff.timer = this->timeQueue.createTimer(iocpContext->readBuff.timeout, delayTimeByReceive, iocpContext);
			}

			result = this->realReceive(iocpContext);

			if (IOCP_PENDING != result)
			{
				// 接受失败，重置 重叠结构
				this->cleanOlp(&iocpContext->readBuff);
			}
		}
	}

	//WSARecv()是从一个套接口接收数据的程序。主要用于在重叠模型中接收数据。
	/*
	  s：一个标识已连接套接口的描述字。
	  lpBuffers：一个指向WSABUF结构数组的指针。每一个WSABUF结构包含一个缓冲区的指针和缓冲区的长度。
	  dwBufferCount：lpBuffers数组中WSABUF结构的数目。
	  lpNumberOfBytesRecvd：如果接收操作立即结束，一个指向本调用所接收的字节数的指针。
	  lpFlags：一个指向标志位的指针。
	  lpOverlapped：一个指向WSAOVERLAPPED结构的指针（对于非重叠套接口则忽略）。
	  lpCompletionRoutine：一个指向接收操作结束后调用的例程的指针（对于非重叠套接口则忽略）。
	*/
	if (iocpContext->rwLock)
	{
		iocpContext->rwLock->unLock();
	}

	return result;
}

int IOCPNetwork::sendContent(void * clientSocket, byte * clientSocketBuff, unsigned long clientBuffLen, unsigned long timeout, IOCPProcCallBack callBack, void * param)
{
	if (!this->isAlreadyInitialize)
	{
		//未初始化
		return IOCP_UNDEFINED;
	}

	IOCPContext *iocpContext = reinterpret_cast<IOCPContext*>(clientSocket);

	// 操作进行中
	int result = IOCP_PENDING;

	if (iocpContext->rwLock)
	{
		iocpContext->rwLock->readLock();
	}

	if (IOCP_NORMAL != iocpContext->status)
	{
		// 套接字正常 允许同时有一个读操作和写操作
		result = iocpContext->status;
	}
	else if (this->sessionTimeout(iocpContext))
	{
		result = IOCP_SESSIONTIMEO;
	}
	else
	{
		assert(iocpContext->writeBuff.status == IOCP_NONE);

		iocpContext->writeBuff.buffer = clientSocketBuff;

		iocpContext->writeBuff.length = clientBuffLen;

		assert(iocpContext->writeBuff.timer == NULL);

		iocpContext->writeBuff.proc = callBack;

		iocpContext->writeBuff.param = param;

		iocpContext->writeBuff.timeout = timeout;

		iocpContext->writeBuff.realLength = clientBuffLen;

		iocpContext->writeBuff.status = IOCP_SEND;

		//检查是否超过速度限制
		size_t delay = 0;

		if (iocpContext->readBuff.speedLimit > 0 && iocpContext->readBuff.lastCompleteTime != 0)
		{
			//获取运行时间
			__int64 execTime = this->hrt.getCounter((iocpContext->writeBuff.sendDataNUmber / iocpContext->writeBuff.speedLimit) * 1.0);

			//完成时间
			execTime += iocpContext->startTime;

			//完成时间提前 说明时间超标
			if (iocpContext->writeBuff.lastCompleteTime > execTime)
			{
				// 减少发送的包数据大小
				// 计算 定时器触发时间
				this->hrt.getMS(iocpContext->writeBuff.lastCompleteTime - execTime);
			}
		}

		//超时
		if (delay > 0)
		{
			// 创建定时器，并返回成功.等真正定时器回调【回调函数】
			iocpContext->writeBuff.status = IOCP_DELAY_READ;

			iocpContext->writeBuff.timer = this->timeQueue.createTimer(delay, delayTimeBySend, iocpContext);
		}
		else
		{
			//如果设置了超时时间
			if (iocpContext->writeBuff.timeout > 0)
			{
				//创建定时器
				iocpContext->writeBuff.timer = this->timeQueue.createTimer(iocpContext->writeBuff.timeout, delayTimeBySend, iocpContext);
			}

			result = this->realSend(iocpContext);

			if (IOCP_PENDING != result)
			{
				// 接受失败，重置 重叠结构
				this->cleanOlp(&iocpContext->writeBuff);
			}
		}
	}

	//WSARecv()是从一个套接口接收数据的程序。主要用于在重叠模型中接收数据。
	/*
	  s：一个标识已连接套接口的描述字。
	  lpBuffers：一个指向WSABUF结构数组的指针。每一个WSABUF结构包含一个缓冲区的指针和缓冲区的长度。
	  dwBufferCount：lpBuffers数组中WSABUF结构的数目。
	  lpNumberOfBytesRecvd：如果接收操作立即结束，一个指向本调用所接收的字节数的指针。
	  lpFlags：一个指向标志位的指针。
	  lpOverlapped：一个指向WSAOVERLAPPED结构的指针（对于非重叠套接口则忽略）。
	  lpCompletionRoutine：一个指向接收操作结束后调用的例程的指针（对于非重叠套接口则忽略）。
	*/
	if (iocpContext->rwLock)
	{
		iocpContext->rwLock->unLock();
	}

	return result;
}

/*
 添加关联输入输出完成端口
*/
iocpKey IOCPNetwork::add(HANDLE h, unsigned long sessionTimeo, unsigned long readSpeedLmt, unsigned long writeSpeedLmt, bool isFile, bool sync)
{
	IOCPContext *contnext = this->allocContnext();

	contnext->handler = h;

	contnext->type = isFile ? IOCP_HANDLE_FILE : IOCP_HANDLE_SOCKET;

	contnext->rwLock = NULL;

	contnext->sessionTimeout = sessionTimeo;

	contnext->readBuff.speedLimit = readSpeedLmt;

	contnext->writeBuff.speedLimit = writeSpeedLmt;

	contnext->startTime = this->hrt.getNow();

	bool result = true;

	//加锁
	this->lockObj.lockUp();

	do
	{
		//关联输入输出完成端口
		if (this->iopcHandle != CreateIoCompletionPort(h, this->iopcHandle, reinterpret_cast<ULONG_PTR>(contnext), 0))
		{
			assert(0);

			result = false;

			break;
		}

		if (sync)
		{
			//同步

			contnext->rwLock = lockPool.allocate();
		}

		connectStock.insert(std::pair<HANDLE, IOCPContext*>(h, contnext));

	} while (0);

	this->lockObj.unLock();

	if (result)
	{
		return contnext;
	}
	else
	{
		delete contnext;
		return IOCP_NULLKEY;
	}
}

void __stdcall IOCPNetwork::delayTimeByReceive(void * param, unsigned char str)
{

}



//初始化上下文
IOCPNetwork::IOCPContext * IOCPNetwork::allocContnext()
{
	IOCPContext *contnext = new IOCPContext();

	memset(contnext, 0, sizeof(IOCPContext));

	return contnext;
}

//会话是否超时
bool IOCPNetwork::sessionTimeout(IOCPContext * iocpContnext)
{
	if (iocpContnext->sessionTimeout == 0)
	{
		//永不超时
		return false;
	}

	return this->hrt.getMS(this->hrt.getNow() - iocpContnext->startTime) > iocpContnext->sessionTimeout;
}
